﻿#region Creditos

/* Autor: Edilberto Sánchez Forero	*/
/* Email: esanchezfo@gmail.com		*/
/* Licencia: LGPL, Software Libre	*/
/* País: Colombia, Bogotá			*/

#endregion

#region Librerias

using System;
using System.Collections.Generic;
using System.Data;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Collections.Specialized;

using ESF.General;
using ESF.General.Entity;
using ESF.Web.ServerControls;
using System.Text;

#endregion


namespace ESF.Web
{
	public static class GridLoader
	{
		#region Constantes

		public const string HIDITEMID = "hidItemID";
		public const string CHKSELECT = "chkSelect";

		#endregion


		#region Limpieza
				
		public static void Clear(GridView pGrid, DataPagging pDataPagging = null)
		{
			pGrid.DataSource = null;
			pGrid.DataBind ();
			
			pGrid.SelectedIndex = -1;
			pGrid.EditIndex = -1;

			pGrid.Visible = false;

			if (pDataPagging != null)
			{
				pDataPagging.PageIndexNoChanges = 0;
				pDataPagging.ShowEmptyMessage();
				pDataPagging.Visible = false;

				pDataPagging.ChangeToDefaultPageSize();
			}
		}
		
		#endregion
		
		
		#region SeleccionMultiple

		public static void SelectAllInPage (GridView pGrid, string pISelectableControlID)
		{
			bool selectableValue;


			selectableValue = true;

			foreach (GridViewRow row in pGrid.Rows)
			{
				 selectableValue = (row.FindControl (pISelectableControlID) as ISelectable).filSelected && selectableValue;
			}


			foreach (GridViewRow row in pGrid.Rows)
			{
				(row.FindControl (pISelectableControlID) as ISelectable).filSelected = !selectableValue;
			}
		}


		public static void SelectAllInPage(DataList pDataList, string pISelectableControlID)
		{
			bool selectableValue;


			selectableValue = true;

			foreach (DataListItem row in pDataList.Items)
			{
				selectableValue = (row.FindControl(pISelectableControlID) as ISelectable).filSelected && selectableValue;
			}


			foreach (DataListItem row in pDataList.Items)
			{
				(row.FindControl(pISelectableControlID) as ISelectable).filSelected = !selectableValue;
			}
		}


		public static void SetCheckedField (GridViewRow pGridViewRow, bool pChecked, string pCheckControlID = CHKSELECT)
		{
			(pGridViewRow.FindControl(pCheckControlID) as CheckBox).Checked = pChecked; 
		}


		/// <summary>
		/// Asigna el valor como el valor de un campo oculto denominado "hidItemID"
		/// </summary>
		public static void SetHiddenFieldForID(GridViewRow pGridViewRow, int pID)
		{
			SetHiddenFieldForID(pGridViewRow, pID.ToString());
		}


		/// <summary>
		/// Asigna el valor como el valor de un campo oculto denominado "hidItemID"
		/// </summary>
		public static void SetHiddenFieldForID(GridViewRow pGridViewRow, string pID)
		{
			HiddenField hidItemID;


			hidItemID = (pGridViewRow.FindControl("hidItemID") as HiddenField);

			if (hidItemID == null)
			{
				throw new Exception("The control HiddenField to store the ID was not found in the Grid");
			}

			hidItemID.Value = pID;
		}


		public static bool RemoveRowsByControl (GridView pGridView, string pControlID, string pValueForCompare)
		{
			bool removed;


			removed = false;

			for (int i = 0; i < pGridView.Rows.Count; i++)
			{
				if (GetValueForControlRow (pGridView.Rows[i], pControlID) == pValueForCompare)
				{
					pGridView.DeleteRow (i);

					removed = true;
				}
			}

			return removed;
		}


		public static bool RemoveRowsByColumn (GridView pGridView, string pColumnName, string pValueForCompare)
		{
			bool removed;


			removed = false;

			for (int i = 0; i < pGridView.Rows.Count; i++)
			{
				if (GetValueForColumnRow (pGridView, pGridView.Rows[i], pColumnName) == pValueForCompare)
				{
					pGridView.DeleteRow(i);

					removed = true;
				}
			}

			return removed;
		}


		public static void CheckHeaderAll (GridView pGridView, string pChkHeaderControlName, string pChkControlName = CHKSELECT)
		{
			bool isChecked;
		

			if (pGridView.Rows.Count == 0) { return; }
	
			isChecked = (pGridView.HeaderRow.FindControl (pChkHeaderControlName) as CheckBox).Checked;
		
			foreach (GridViewRow row in pGridView.Rows)
			{
				(row.FindControl (pChkControlName) as CheckBox).Checked = isChecked;
			}
		}


		public static bool RemoveSelectedRows (GridView pGridView)
		{
			return RemoveSelectedRows (pGridView, CHKSELECT);
		}
		


		public static bool RemoveSelectedRows
		(
			GridView pGridView, string pChkControlName
		)
		{
			bool removed;


			removed = false;

			try
			{
				for (int i = 0; i < pGridView.Rows.Count; i++)
				{
					if (IsSelectedRow (pGridView.Rows [i], pChkControlName))
					{
						pGridView.DeleteRow (i);

						removed = true;
					}
				}
				
				return removed;
			}
			catch (Exception pEx)
			{
				throw new GenericException ("No se pudo leer los elementos seleccionados", pEx);
			}
		}


		public static List<GridViewRow> GetSelectedRows
		(
			GridView pGridView
		)
		{
			return GetSelectedRows (pGridView, CHKSELECT);
		}


		public static List<GridViewRow> GetSelectedRows
		(
			GridView pGridView, string pChkControlName
		)
		{
			List<GridViewRow> result;


			result = new List<GridViewRow>(); 
			
			for (int i = 0; i < pGridView.Rows.Count; i++)
			{
				if (IsSelectedRow (pGridView.Rows [i], pChkControlName))
				{
					result.Add (pGridView.Rows [i]);
				}
			}

			return result;
		}
		
		
		public static List<NameValueCollection> GetSelectedItemCellTextsAllCols
		(
			GridView pGridView, string pChkControlName
		)
		{
			NameValueCollection tmpCurrentResult;
			
			string tmpValue;

			List<NameValueCollection> result;


			result = new List<NameValueCollection> ();			
		
			foreach (GridViewRow row in pGridView.Rows)
			{
				if (IsSelectedRow (row, pChkControlName))
				{
					tmpCurrentResult = new NameValueCollection ();
						
					tmpCurrentResult.Add (string.Empty, row.RowIndex.ToString ());
						
					for (int colIndex = 0; colIndex < pGridView.Columns.Count; colIndex ++)
					{
						tmpValue = row.Cells [colIndex].Text;
							
						tmpCurrentResult.Add (pGridView.Columns [colIndex].HeaderText, tmpValue);
					}
						
					result.Add (tmpCurrentResult);
				}
			}

			return result;
		}
		

		public static List<int> GetSelectedIdentifiersAsInt
		(
			GridView pGridView
		)
		{
			return GetSelectedIdentifiersAsInt (pGridView, HIDITEMID);
		}

		
		public static List<int> GetSelectedIdentifiersAsInt
		(
			GridView pGridView, string pIDControlColumnName 
		)
		{
			return GetSelectedIdentifiersAsInt (pGridView, CHKSELECT, pIDControlColumnName);
		}


		public static List<int> GetSelectedIdentifiersAsInt
		(
			GridView pGridView, string pChkControlName, string pIDControlColumnName 
		)
		{
			return TextHelper.ConvertoToIntList (GetSelectedIdentifiersAsString (pGridView, pChkControlName, pIDControlColumnName));
		}
		
		
		public static List<string> GetSelectedIdentifiersAsString 
		(
			GridView pGridView
		)
		{
			return GetSelectedIdentifiersAsString (pGridView, HIDITEMID);
		}


		public static List<string> GetSelectedIdentifiersAsString 
		(
			GridView pGridView, string pIDControlColumnName 
		)
		{
			return GetSelectedIdentifiersAsString (pGridView, CHKSELECT, pIDControlColumnName);
		}


		public static List<string> GetSelectedIdentifiersAsString 
		(
			GridView pGridView, string pChkControlName, string pIDControlColumnName 
		)
		{
			List<string> result;


			result = new List<string>(); 
			
			foreach (GridViewRow row in pGridView.Rows)
			{
				if (IsSelectedRow (row, pChkControlName))
				{
					result.Add (GetValueForRow (pGridView, row, pIDControlColumnName));
				}
			}

			return result;
		}


		public static List<string> GetSelectedItemList
		(
			GridView pGridView, string pChkControlName, string pKeyControlOrColumnName
		)
		{
			List<string> result;


			result = new List<string> ();

			foreach (NameValueCollection items in GetSelectedItems(pGridView, pChkControlName, new string[] { pKeyControlOrColumnName }))
			{			
				foreach (string key in items.AllKeys)
				{
					result.Add (items [key]);
				}
			}

			return result;
		}


		public static List<NameValueCollection> GetSelectedItems 
		(
			GridView pGridView, string pChkControlName, params string [] pKeyControlOrColumnNames 
		)
		{
			List<string> columnNames;

			NameValueCollection tmpCurrentResult;
			
			List<NameValueCollection> result;


			result = new List<NameValueCollection> ();

			if (pGridView == null)
			{
				return result;
			}
			
			columnNames = new List<string> ();

			if (pKeyControlOrColumnNames == null || pKeyControlOrColumnNames.Length == 0)
			{
				foreach (DataControlField col in pGridView.Columns)
				{	
					columnNames.Add (col.HeaderText);
				}

				pKeyControlOrColumnNames = columnNames.ToArray ();
			}

			foreach (GridViewRow row in pGridView.Rows)
			{
				if (IsSelectedRow (row, pChkControlName))
				{
					tmpCurrentResult = new NameValueCollection ();
						
					tmpCurrentResult.Add (string.Empty, row.RowIndex.ToString ());
						
					foreach (string kcn in pKeyControlOrColumnNames)
					{
						tmpCurrentResult.Add (kcn, GetValueForRow (pGridView, row, kcn));
					}
						
					result.Add (tmpCurrentResult);
				}
			}

			return result;
		}


		public static List<Couple<string, bool>> GetIdentifiersAsString
		(
			GridView pGridView, string pChkControlName = CHKSELECT, string pIDControlColumnName = HIDITEMID
		)
		{
			List<Couple<string, bool>> result;


			result = new List<Couple<string, bool>> ();

			foreach (GridViewRow row in pGridView.Rows)
			{
				result.Add (
					new Couple<string,bool> () 
					{ 
						Key = GetValueForControlRow (row, pIDControlColumnName), 
						Value = IsSelectedRow(row, pChkControlName)
					});
			}

			return result;
		}


		public static List<Couple<int?, bool>> GetIdentifiersAsInt
		(
			GridView pGridView, string pChkControlName = CHKSELECT, string pIDControlColumnName = HIDITEMID
		)
		{
			List<Couple<int?, bool>> result;


			result = new List<Couple<int?, bool>>();

			foreach (GridViewRow row in pGridView.Rows)
			{
				result.Add(
					new Couple<int?, bool>()
					{
						Key = GetValueIDForRow(row, pIDControlColumnName),
						Value = IsSelectedRow(row, pChkControlName)
					});
			}

			return result;
		}
		

		public static int GetGridViewRowIndex (object pCommandSource_ControlFromRow)
		{
			return GetGridViewRow (pCommandSource_ControlFromRow).RowIndex;
		}


		public static GridViewRow GetGridViewRow (object pCommandSource)
		{
			return (pCommandSource as Control).NamingContainer as GridViewRow;
		}


		public static int GetValueIDForCommandButton (object pCommandButton)
		{
			return Convert.ToInt32 (GetValueIDStringForCommandButton (pCommandButton));
		}


		public static string GetValueIDStringForCommandButton (object pCommandButton)
		{
			Control control;


			control = pCommandButton as Control;

			if (control == null) { throw new Exception ("The argument provider in order to get the ID for Row of the Grid is not a control"); }

			return GetValueIDStringForCommand (control.NamingContainer);
		}


		public static string GetValueIDStringForCommand (Control pNamingContainer)
		{
			return GetValueIDStringForCommand (pNamingContainer, HIDITEMID);
		}


		public static int GetValueIDForCommand (Control pNamingContainer, string pHidControlID = HIDITEMID)
		{
			return Convert.ToInt32 (GetValueIDStringForCommand (pNamingContainer, pHidControlID));
		}


		 public static string GetValueIDStringForCommand (Control pNamingContainer, string pHidControlID = HIDITEMID)
		{
			return (pNamingContainer.FindControl (pHidControlID) as HiddenField).Value;
		}


		public static int? GetValueIDForRow (GridViewRow pRow)
		{
			return GetValueIDForRow (pRow, HIDITEMID);
		}


		public static string GetValueIDStringForRow (GridViewRow pRow)
		{
			return GetValueIDStringForRow (pRow, HIDITEMID);
		}


		public static int? GetValueIDForRow (GridViewRow pRow, string pIDControlColumnName = HIDITEMID)
		{
			string value;


			value = GetValueIDStringForRow (pRow, pIDControlColumnName); 

			if (!string.IsNullOrEmpty (value))
			{
				return int.Parse (value);
			}

			return null;
		}


		public static string GetValueIDStringForRow (GridViewRow pRow, string pIDControlColumnName = HIDITEMID)
		{
			return GetValueForRow (null, pRow, pIDControlColumnName);
		}


		public static void SetValueIDForRow (GridViewRow pRow, string pID)
		{
			SetValueIDForRow (pRow, HIDITEMID, pID);
		}


		public static void SetValueIDForRow (GridViewRow pRow, string pHidIDControlName, string pID)
		{
			(pRow.FindControl (pHidIDControlName) as HiddenField).Value = pID;
		}
		
		
		public static void SetValueIDForRow (GridViewRow pRow, int? pID)
		{
			SetValueIDForRow (pRow, HIDITEMID, pID);
		}


		public static void SetValueIDForRow (GridViewRow pRow, string pHidIDControlName, int? pID)
		{
			if (pID != null)
			{
				SetValueIDForRow (pRow, pHidIDControlName, pID.ToString ());
			}
		}
					

		public static string GetValueForRow (GridView pGridView, GridViewRow pRow, string pColumnNameIDControl = HIDITEMID)
		{
			Exception ex;


			try
			{
				return GetValueForColumnRow (pGridView, pRow, pColumnNameIDControl);
			}
			catch (Exception pEx)
			{
				ex = pEx;
			}

			try
			{
				return GetValueForControlRow (pRow, pColumnNameIDControl);
			}
			catch (Exception pEx)
			{
				throw new Exception (string.Format ("Column or control not found: {0} in {1}", pColumnNameIDControl, pGridView.ID), pEx);
			}
		}



		public static string GetValueForColumnRow (GridView pGridView, GridViewRow pRow, string pColumnName = HIDITEMID)
		{
			StringBuilder stbAvailableColumns = new StringBuilder();


			if (pGridView != null && pGridView.Columns.Count > 0)
			{
				for (int colIndex = 0; colIndex < pGridView.Columns.Count; colIndex++)
				{
					stbAvailableColumns.AppendFormat("{0} posición {1}, ", pGridView.Columns[colIndex].HeaderText, colIndex);

					if (string.Compare(pGridView.Columns[colIndex].HeaderText, pColumnName, true) == 0)
					{
						return pRow.Cells[colIndex].Text.Replace("&#241;", " ").Replace("&nbsp;", " ").Trim();
					}
				}
			}

			throw new Exception(
				string.Format("The column {0} is not part of gridview {1}.\nAvailable columns ({2}): {3}",
					pColumnName, (pGridView == null ? "[Not given]" : pGridView.ID),
					(pGridView == null ? "[Not given grid]" : pGridView.Columns.Count.ToString()), stbAvailableColumns.ToString()));
		}


		public static string GetValueForControlRow<C> (C pRow, string pControlID = HIDITEMID) where C : Control
		{
			Control tmpControl;


			tmpControl = pRow.FindControl (pControlID);
					
			// Puede que sea una Columna
			if (tmpControl == null)
			{
				throw new Exception(string.Format("The control {0} is not defined for row {1}", pControlID, pRow.ID));
			}
			
			if (tmpControl is HiddenField)
			{
				return (tmpControl as HiddenField).Value;
			}
			else if (tmpControl is DropDownList)
			{
				return (tmpControl as DropDownList).SelectedValue;
			}
			else if (tmpControl is System.Web.UI.WebControls.Calendar) 
			{
				return (tmpControl as System.Web.UI.WebControls.Calendar).SelectedDate.ToString ();
			}
			else if (tmpControl is CheckBox)
			{
				return (tmpControl as CheckBox).Checked.ToString ();
			}
			else if (tmpControl is Label)
			{
				return (tmpControl as Label).Text;
			}
			else if (tmpControl is TextBox)
			{
				return (tmpControl as TextBox).Text;
			}
			else if (tmpControl is LinkButton)
			{
				return (tmpControl as LinkButton).Text;
			}
			else if (tmpControl is HyperLink)
			{
				return (tmpControl as HyperLink).NavigateUrl;
			}

			throw new Exception(string.Format("The read of control {0} of type {1} from row {2} is not supported", pControlID, tmpControl.GetType (), pRow.ID));
		}

		
		public static bool IsSelectedRow(GridView pGrid, string pChkControlName = CHKSELECT)
		{
			foreach (GridViewRow row in pGrid.Rows)
			{
				if (IsSelectedRow (row, pChkControlName))
				{
					return true;
				}
			}

			return false;
		}


		public static bool IsSelectedRow(GridViewRow pRow, string pChkControlName = CHKSELECT)
		{
			CheckBox chkTemp;


			chkTemp = (pRow.FindControl (pChkControlName) as CheckBox);

			if (chkTemp == null) { return false; }

			return chkTemp.Checked;
		}

		#endregion
	
	
		#region Carga

		public static bool LoadGrid<O> (GridView pGrid, DataPagging pDataPagging, BrowseResults<O> pPagedValues)
		{
			Clear(pGrid, pDataPagging);

			if (DataHelper.IsEmpty (pPagedValues)) 
			{
				if (pDataPagging != null)
				{
					pDataPagging.ShowEmptyMessage ();
					pGrid.Visible = false;
					return false;
				}

				if (string.IsNullOrEmpty (pGrid.EmptyDataText))
				{
					pGrid.EmptyDataText = "No fueron encontrados registros para su consulta";
				}
				 
				pGrid.Visible = true;
				return false; 
			}
			
			if (pDataPagging != null)
			{
				pDataPagging.PaggingInfoNoChanges = pPagedValues.PaggingInfo; 
				pDataPagging.Visible = true;				
				pDataPagging.ToolTip = string.Format ("Process in server time take {0}", TextHelper.ToStringMS (pPagedValues.calProcessingDurationms));
			}

			return LoadGrid<O> (pGrid, pPagedValues.Results, (pDataPagging == null ? true : false));
		}


		public static bool LoadGrid<O> (GridView pGrid, IEnumerable<O> pItems) 
		{
			return LoadGrid<O> (pGrid, pItems, true);
		}


		public static bool LoadGrid<O> (GridView pGrid, IEnumerable<O> pItems, bool pShowEmptyMessage) 
		{
			Clear(pGrid);

			
			if (DataHelper.IsEmpty (pItems))
			{
				pGrid.Visible = pShowEmptyMessage;

				if (string.IsNullOrEmpty (pGrid.EmptyDataText))
				{
					pGrid.EmptyDataText = "No fueron encontrados registros para su consulta";
				}
				
				return false;
			}			
			
			pGrid.Visible = true;
			pGrid.DataSource = pItems;
			pGrid.DataBind ();

			return true;
		}


		public static bool LoadGrid<O>(GridView pGrid, O [] pItems)
		{
			Clear(pGrid);

			
			pGrid.Visible = true;

			if (DataHelper.IsEmpty (pItems))
			{
				if (string.IsNullOrEmpty(pGrid.EmptyDataText))
				{
					pGrid.EmptyDataText = "No fueron encontrados registros para su consulta";
				}

				return false;
			}

			pGrid.DataSource = pItems;
			pGrid.DataBind();

			return true;
		}


		public static bool LoadGrid (GridView pGrid, DataPagging pDataPagging, DataTable pTable)
		{
			Clear(pGrid, pDataPagging);

			if (DataHelper.IsEmpty (pTable)) 
			{
				if (pDataPagging != null)
				{
					pDataPagging.ShowEmptyMessage ();
					pGrid.Visible = false;
					return false;
				}

				if (string.IsNullOrEmpty (pGrid.EmptyDataText))
				{
					pGrid.EmptyDataText = "No fueron encontrados registros para su consulta";
				}
				 
				pGrid.Visible = true;
				return false; 
			}
			
			if (pDataPagging != null)
			{
				pDataPagging.Visible = true;
				pDataPagging.PaggingInfoNoChanges = new PaggingInfo () { PageIndex = pDataPagging.PageIndex, PageSize = pDataPagging.PageSize, RowCount = DataHelper.GetInt (DataHelper.GetFirstRow (pTable), "RCount", pTable.Rows.Count) };
			}

			return LoadGrid (pGrid, pTable);
		}
		
		
		public static bool LoadGrid (GridView pGrid, DataTable pdtbTable)
		{
			Clear(pGrid);

			pGrid.Visible = true;
		
			if (DataHelper.IsEmpty (pdtbTable))
			{
				if (string.IsNullOrEmpty(pGrid.EmptyDataText))
				{
					pGrid.EmptyDataText = "No fueron encontrados registros para su consulta";
				}
				
				return false;
			}

			pGrid.DataSource = pdtbTable;
			pGrid.DataBind ();

			return true;
		}

		#endregion


		#region Seleccion Unica

		public static void AddRowRadioButton (GridViewRow pRow, string pUniqueName)
		{
			AddRowRadioButton (pRow, pUniqueName, false);
		}
		
		
		public static void AddRowRadioButton (GridViewRow pRow, string pLiteralControlName, bool pChecked)
		{
			Literal literal;


			literal = (pRow.FindControl (pLiteralControlName) as Literal);

			literal.Text = string.Format(@"<input type=""radio"" name=""RowSelector_{0}"" id=""RowSelector_{0}"" value=""{1}""", pLiteralControlName, pRow.RowIndex);

			if (pChecked)
			{
				literal.Text += @" checked=""checked""";
			}

			literal.Text += " />";
		}


		public static string GetRadioButtonValue (string pLiteralControlName)
		{
			return RequestHelper.GetPostParam (string.Format ("RowSelector_{0}", pLiteralControlName));
		}


		public static int? GetRadioButtonValueInt (string pLiteralControlName)
		{
			return RequestHelper.GetPostParamInt (string.Format ("RowSelector_{0}", pLiteralControlName));
		}


		public static long? GetRadioButtonValueLong (string pLiteralControlName)
		{
			return RequestHelper.GetPostParamLong (string.Format ("RowSelector_{0}", pLiteralControlName));
		}

		#endregion
	}
}
